package com.egene.tw.data;

import com.egene.tw.activity.signs.BarChartData;
import com.egene.tw.activity.signs.BarChartItemData;
import com.egene.tw.data.entity.BloodData;
import com.egene.tw.data.entity.DeviceSetting;
import com.egene.tw.data.entity.FatigueData;
import com.egene.tw.data.entity.HeartData;
import com.egene.tw.data.entity.NetResult;
import com.egene.tw.data.entity.OxygenData;
import com.egene.tw.data.entity.SleepData;
import com.egene.tw.data.entity.StepData;
import com.egene.tw.data.net.ApiBuilder;
import com.egene.tw.data.utils.CalUtils;
import com.egene.tw.data.utils.DateFormUtils;
import com.egene.tw.data.wrapper.HomeData;
import com.egene.tw.data.wrapper.OneKeyMeasureData;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.realm.Realm;
import io.realm.Sort;

/**
 * Created by wzx on 2018/6/6.
 */

public class DataRepository implements EDataSource {

    private static DataRepository instance = new DataRepository();

    private DataRepository() {
    }

    public static DataRepository getInstance() {
        return instance;
    }

    public String currUserId() {
        String userId;
        Realm realm = Realm.getDefaultInstance();
        try {
            userId = RealmHelper.getCurrUserId(realm);
        } finally {
            realm.close();
        }
        return userId;
    }

    @Override
    public Observable<Object> saveHeartData(final long time, final int value) {
        return Observable
                .create(new ObservableOnSubscribe<Object>() {
                    @Override
                    public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            HeartData data = new HeartData();
                            data.setValue(value);
                            data.setTime(time);
                            data.setUserId(currUserId());

                            realm.beginTransaction();
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                        emitter.onNext("");
                        emitter.onComplete();
                    }
                });
    }

    @Override
    public Observable<List<HeartData>> heartDataList() {
        return Observable.create(
                new ObservableOnSubscribe<List<HeartData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<HeartData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<HeartData> list = realm.where(HeartData.class).equalTo("userId", currUserId()).findAllSorted("time", Sort.DESCENDING);
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> heartBarDataByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneDayStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 24; i++) {
                                long startValue = startTime + (i * DateFormUtils.HOUR);
                                long endValue = startTime + ((i + 1) * DateFormUtils.HOUR) - 1;
                                List<HeartData> list = realm.where(HeartData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (HeartData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + i, 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> heartBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<HeartData> list = realm.where(HeartData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (HeartData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> heartBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<HeartData> list = realm.where(HeartData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (HeartData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + (i + 1), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> heartAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<HeartData> list = realm.where(HeartData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (HeartData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> heartAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<HeartData> list = realm.where(HeartData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (HeartData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> heartAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<HeartData> list = realm.where(HeartData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (HeartData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<Object> saveOxygenData(final long time, final int value) {
        return Observable
                .create(new ObservableOnSubscribe<Object>() {
                    @Override
                    public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            OxygenData data = new OxygenData();
                            data.setValue(value);
                            data.setTime(time);
                            data.setUserId(currUserId());

                            realm.beginTransaction();
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                        emitter.onNext("");
                        emitter.onComplete();
                    }
                });
    }

    @Override
    public Observable<List<OxygenData>> oxygenDataList() {
        return Observable.create(
                new ObservableOnSubscribe<List<OxygenData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<OxygenData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<OxygenData> list = realm.where(OxygenData.class).equalTo("userId", currUserId()).findAllSorted("time", Sort.DESCENDING);
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> oxygenBarDataByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneDayStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 24; i++) {
                                long startValue = startTime + (i * DateFormUtils.HOUR);
                                long endValue = startTime + ((i + 1) * DateFormUtils.HOUR) - 1;
                                List<OxygenData> list = realm.where(OxygenData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (OxygenData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + i, 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> oxygenBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<OxygenData> list = realm.where(OxygenData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (OxygenData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> oxygenBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<OxygenData> list = realm.where(OxygenData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (OxygenData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + (i + 1), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> oxygenAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<OxygenData> list = realm.where(OxygenData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (OxygenData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> oxygenAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<OxygenData> list = realm.where(OxygenData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (OxygenData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> oxygenAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<OxygenData> list = realm.where(OxygenData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            int total = 0;
                            if (list.size() > 0) {
                                for (OxygenData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<Object> saveBloodData(final long time, final int valueHigh, final int valueLow) {
        return Observable
                .create(new ObservableOnSubscribe<Object>() {
                    @Override
                    public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            BloodData data = new BloodData();
                            data.setHighValue(valueHigh);
                            data.setLowValue(valueLow);
                            data.setTime(time);
                            data.setUserId(currUserId());

                            realm.beginTransaction();
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                        emitter.onNext("");
                        emitter.onComplete();
                    }
                });

    }

    @Override
    public Observable<List<BloodData>> bloodDataList() {
        return Observable.create(
                new ObservableOnSubscribe<List<BloodData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<BloodData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<BloodData> list = realm.where(BloodData.class).equalTo("userId", currUserId()).findAllSorted("time", Sort.DESCENDING);
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> bloodBarDataByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneDayStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 24; i++) {
                                long startValue = startTime + (i * DateFormUtils.HOUR);
                                long endValue = startTime + ((i + 1) * DateFormUtils.HOUR) - 1;
                                List<BloodData> list = realm.where(BloodData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int high = 0;
                                int low = 0;
                                if (list.size() > 0) {
                                    for (BloodData item : list) {
                                        if (high == 0) {
                                            high = item.getHighValue();
                                        } else if (high < item.getHighValue()) {
                                            high = item.getHighValue();
                                        }
                                        if (low == 0) {
                                            low = item.getLowValue();
                                        } else if (low > item.getLowValue()) {
                                            low = item.getLowValue();
                                        }
                                    }
                                }
                                barList.add(new BarChartItemData("" + i, high, low, 0));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> bloodBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<BloodData> list = realm.where(BloodData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int high = 0;
                                int low = 0;
                                if (list.size() > 0) {
                                    for (BloodData item : list) {
                                        if (high == 0) {
                                            high = item.getHighValue();
                                        } else if (high < item.getHighValue()) {
                                            high = item.getHighValue();
                                        }
                                        if (low == 0) {
                                            low = item.getLowValue();
                                        } else if (low > item.getLowValue()) {
                                            low = item.getLowValue();
                                        }
                                    }
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), high, low, 0));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> bloodBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<BloodData> list = realm.where(BloodData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int high = 0;
                                int low = 0;
                                if (list.size() > 0) {
                                    for (BloodData item : list) {
                                        if (high == 0) {
                                            high = item.getHighValue();
                                        } else if (high < item.getHighValue()) {
                                            high = item.getHighValue();
                                        }
                                        if (low == 0) {
                                            low = item.getLowValue();
                                        } else if (low > item.getLowValue()) {
                                            low = item.getLowValue();
                                        }
                                    }
                                }
                                barList.add(new BarChartItemData("" + (i + 1), high, low, 0));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> bloodAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<BloodData> list = realm.where(BloodData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (BloodData item : list) {
                                    if (high == 0) {
                                        high = item.getHighValue();
                                    } else if (high < item.getHighValue()) {
                                        high = item.getHighValue();
                                    }
                                    if (low == 0) {
                                        low = item.getLowValue();
                                    } else if (low > item.getLowValue()) {
                                        low = item.getLowValue();
                                    }
                                }
                                pj = (high - low) / 3 + low;
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> bloodAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<BloodData> list = realm.where(BloodData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (BloodData item : list) {
                                    if (high == 0) {
                                        high = item.getHighValue();
                                    } else if (high < item.getHighValue()) {
                                        high = item.getHighValue();
                                    }
                                    if (low == 0) {
                                        low = item.getLowValue();
                                    } else if (low > item.getLowValue()) {
                                        low = item.getLowValue();
                                    }
                                }
                                pj = (high - low) / 3 + low;
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<int[]> bloodAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<int[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<int[]> emitter) throws Exception {
                        int pj = 0;
                        int high = 0;
                        int low = 0;

                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<BloodData> list = realm.where(BloodData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (BloodData item : list) {
                                    if (high == 0) {
                                        high = item.getHighValue();
                                    } else if (high < item.getHighValue()) {
                                        high = item.getHighValue();
                                    }
                                    if (low == 0) {
                                        low = item.getLowValue();
                                    } else if (low > item.getLowValue()) {
                                        low = item.getLowValue();
                                    }
                                }
                                pj = (high - low) / 3 + low;
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new int[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    @Override
    public Observable<List<FatigueData>> fatigueDataList() {
        return Observable.create(
                new ObservableOnSubscribe<List<FatigueData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<FatigueData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<FatigueData> list = realm.where(FatigueData.class).equalTo("userId", currUserId()).findAllSorted("time", Sort.DESCENDING);
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> fatigueBarDataByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneDayStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 24; i++) {
                                long startValue = startTime + (i * DateFormUtils.HOUR);
                                long endValue = startTime + ((i + 1) * DateFormUtils.HOUR) - 1;
                                List<FatigueData> list = realm.where(FatigueData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (FatigueData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + i, 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> fatigueBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<FatigueData> list = realm.where(FatigueData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (FatigueData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> fatigueBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<FatigueData> list = realm.where(FatigueData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (FatigueData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + (i + 1), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<float[]> fatigueAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<float[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<float[]> emitter) throws Exception {
                        float pj = 0;
                        float high = 0;
                        float low = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<FatigueData> list = realm.where(FatigueData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            float total = 0;
                            if (list.size() > 0) {
                                for (FatigueData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new float[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<float[]> fatigueAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<float[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<float[]> emitter) throws Exception {
                        float pj = 0;
                        float high = 0;
                        float low = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<FatigueData> list = realm.where(FatigueData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            float total = 0;
                            if (list.size() > 0) {
                                for (FatigueData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new float[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<float[]> fatigueAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<float[]>() {
                    @Override
                    public void subscribe(ObservableEmitter<float[]> emitter) throws Exception {
                        float pj = 0;
                        float high = 0;
                        float low = 0;

                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<FatigueData> list = realm.where(FatigueData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            float total = 0;
                            if (list.size() > 0) {
                                for (FatigueData item : list) {
                                    if (item.getValue() > high) {
                                        high = item.getValue();
                                    }
                                    if (low == 0) {
                                        low = item.getValue();
                                    } else if (item.getValue() < low) {
                                        low = item.getValue();
                                    }
                                    total += item.getValue();
                                }
                                pj = total / list.size();
                            }
                        } finally {
                            realm.close();
                        }
                        emitter.onNext(new float[]{pj, high, low});
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////

    @Override
    public Observable<StepData> stepBarDataByDay(final long time) {
        return Observable.create(
                new ObservableOnSubscribe<StepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<StepData> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            long time1 = DateFormUtils.oneDayStart(time);
                            StepData data = realm.where(StepData.class).equalTo("userId", currUserId()).equalTo("time", time1).findAllSorted("time", Sort.DESCENDING).first(null);
                            if (data == null) {
                                data = new StepData();
                            } else {
                                data = realm.copyFromRealm(data);
                            }
                            emitter.onNext(data);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    @Override
    public Observable<BarChartData> stepBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<StepData> list = realm.where(StepData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (StepData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> stepBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<StepData> list = realm.where(StepData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int total = 0;
                                if (list.size() > 0) {
                                    for (StepData item : list) {
                                        total += item.getValue();
                                    }
                                    total = total / list.size();
                                }
                                barList.add(new BarChartItemData("" + (i + 1), 0, 0, total));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<StepData> stepAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<StepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<StepData> emitter) throws Exception {
                        int kcal = 0;
                        int juli = 0;
                        int step = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<StepData> list = realm.where(StepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (StepData item : list) {
                                    kcal += item.getKcal();
                                    step += item.getValue();
                                }
                            }
                        } finally {
                            realm.close();
                        }
                        StepData stepData = new StepData();
                        stepData.setKcal(kcal);
                        stepData.setValue(step);
                        stepData.setJuli(juli);
                        emitter.onNext(stepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<StepData> stepAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<StepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<StepData> emitter) throws Exception {
                        int kcal = 0;
                        int juli = 0;
                        int step = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<StepData> list = realm.where(StepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (StepData item : list) {
                                    kcal += item.getKcal();
                                    step += item.getValue();
                                }
                            }
                        } finally {
                            realm.close();
                        }
                        StepData stepData = new StepData();
                        stepData.setKcal(kcal);
                        stepData.setValue(step);
                        stepData.setJuli(juli);
                        emitter.onNext(stepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<StepData> stepAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<StepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<StepData> emitter) throws Exception {
                        int kcal = 0;
                        int juli = 0;
                        int step = 0;

                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<StepData> list = realm.where(StepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (StepData item : list) {
                                    kcal += item.getKcal();
                                    step += item.getValue();
                                }
                            }
                        } finally {
                            realm.close();
                        }
                        StepData stepData = new StepData();
                        stepData.setKcal(kcal);
                        stepData.setValue(step);
                        stepData.setJuli(juli);
                        emitter.onNext(stepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////

    @Override
    public Observable<SleepData> sleepBarDataByDay(final long time) {
        return Observable.create(
                new ObservableOnSubscribe<SleepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<SleepData> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            long time1 = DateFormUtils.oneDayStart(time);
                            SleepData data = realm.where(SleepData.class).equalTo("userId", currUserId()).equalTo("time", time1).findAllSorted("time", Sort.DESCENDING).first(null);
                            if (data == null) {
                                data = new SleepData();
                            } else {
                                data = realm.copyFromRealm(data);
                            }
                            data.setTotal(data.getDeepValue() + data.getShallowValue());
                            emitter.onNext(data);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    @Override
    public Observable<BarChartData> sleepBarDataByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneWeekStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            for (int i = 0; i < 7; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<SleepData> list = realm.where(SleepData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int high = 0;
                                int low = 0;
                                if (list.size() > 0) {
                                    for (SleepData item : list) {
                                        if (high == 0) {
                                            high = item.getDeepValue();
                                        } else if (high < item.getDeepValue()) {
                                            high = item.getDeepValue();
                                        }
                                        if (low == 0) {
                                            low = item.getShallowValue();
                                        } else if (low > item.getShallowValue()) {
                                            low = item.getShallowValue();
                                        }
                                    }
                                }
                                barList.add(new BarChartItemData(DateFormUtils.weekDesc(startValue), high, low, 0));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<BarChartData> sleepBarDataByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<BarChartData>() {
                    @Override
                    public void subscribe(ObservableEmitter<BarChartData> emitter) throws Exception {
                        long startTime = DateFormUtils.oneMonthStart(time);
                        List<BarChartItemData> barList = new ArrayList<>();
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                            calendar.add(Calendar.MONTH, 1);
                            calendar.add(Calendar.DATE, -1);
                            int count = calendar.get(Calendar.DATE);

                            for (int i = 0; i < count; i++) {
                                long startValue = startTime + (i * DateFormUtils.DAY);
                                long endValue = startTime + ((i + 1) * DateFormUtils.DAY) - 1;
                                List<SleepData> list = realm.where(SleepData.class)
                                        .equalTo("userId", currUserId())
                                        .between("time", startValue, endValue)
                                        .findAll();
                                int high = 0;
                                int low = 0;
                                if (list.size() > 0) {
                                    for (SleepData item : list) {
                                        if (high == 0) {
                                            high = item.getDeepValue();
                                        } else if (high < item.getDeepValue()) {
                                            high = item.getDeepValue();
                                        }
                                        if (low == 0) {
                                            low = item.getShallowValue();
                                        } else if (low > item.getShallowValue()) {
                                            low = item.getShallowValue();
                                        }
                                    }
                                }
                                barList.add(new BarChartItemData("" + (i + 1), high, low, 0));
                            }
                        } finally {
                            realm.close();
                        }
                        BarChartData barChartData = new BarChartData();
                        barChartData.setList(barList);
                        emitter.onNext(barChartData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<SleepData> sleepAnalysisByDay(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<SleepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<SleepData> emitter) throws Exception {
                        int deep = 0;
                        int shall = 0;
                        int wlakup = 0;

                        long startTime = DateFormUtils.oneDayStart(time);
                        long endTime = startTime + DateFormUtils.DAY - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<SleepData> list = realm.where(SleepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (SleepData item : list) {
                                    deep += item.getDeepValue();
                                    shall += item.getShallowValue();
                                    wlakup += item.getWalkingTimes();
                                }
                            }
                        } finally {
                            realm.close();
                        }

                        SleepData sleepData = new SleepData();
                        sleepData.setTotal(deep + shall);
                        sleepData.setDeepValue(deep);
                        sleepData.setShallowValue(shall);
                        sleepData.setWalkingTimes(wlakup);
                        emitter.onNext(sleepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<SleepData> sleepAnalysisByWeek(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<SleepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<SleepData> emitter) throws Exception {
                        int deep = 0;
                        int shall = 0;
                        int wlakup = 0;

                        long startTime = DateFormUtils.oneWeekStart(time);
                        long endTime = startTime + (DateFormUtils.DAY * 7) - 1;
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<SleepData> list = realm.where(SleepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (SleepData item : list) {
                                    deep += item.getDeepValue();
                                    shall += item.getShallowValue();
                                    wlakup += item.getWalkingTimes();
                                }
                            }
                        } finally {
                            realm.close();
                        }

                        SleepData sleepData = new SleepData();
                        sleepData.setTotal(deep + shall);
                        sleepData.setDeepValue(deep);
                        sleepData.setShallowValue(shall);
                        sleepData.setWalkingTimes(wlakup);
                        emitter.onNext(sleepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<SleepData> sleepAnalysisByMonth(final long time) {
        return Observable
                .create(new ObservableOnSubscribe<SleepData>() {
                    @Override
                    public void subscribe(ObservableEmitter<SleepData> emitter) throws Exception {
                        int deep = 0;
                        int shall = 0;
                        int wlakup = 0;


                        long startTime = DateFormUtils.oneMonthStart(time);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(DateFormUtils.oneMonthStart(time));
                        calendar.add(Calendar.MONTH, 1);
                        calendar.add(Calendar.DATE, -1);
                        int count = calendar.get(Calendar.DATE);

                        long endTime = startTime + (DateFormUtils.DAY * count) - 1;

                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<SleepData> list = realm.where(SleepData.class)
                                    .equalTo("userId", currUserId())
                                    .between("time", startTime, endTime)
                                    .findAll();
                            if (list.size() > 0) {
                                for (SleepData item : list) {
                                    deep += item.getDeepValue();
                                    shall += item.getShallowValue();
                                    wlakup += item.getWalkingTimes();
                                }
                            }
                        } finally {
                            realm.close();
                        }

                        SleepData sleepData = new SleepData();
                        sleepData.setTotal(deep + shall);
                        sleepData.setDeepValue(deep);
                        sleepData.setShallowValue(shall);
                        sleepData.setWalkingTimes(wlakup);
                        emitter.onNext(sleepData);
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////

    @Override
    public Observable<Object> saveOneKeyData(final long time, final OneKeyMeasureData data) {
        return saveHeartData(time, data.getHeart())
                .flatMap(new Function<Object, ObservableSource<Object>>() {
                    @Override
                    public ObservableSource<Object> apply(Object o) throws Exception {
                        return saveOxygenData(time, data.getOxygen());
                    }
                })
                .flatMap(new Function<Object, ObservableSource<Object>>() {
                    @Override
                    public ObservableSource<Object> apply(Object o) throws Exception {
                        return saveBloodData(time, data.getBloodHigh(), data.getBloodLow());
                    }
                })
                .flatMap(new Function<Object, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(Object o) throws Exception {
                        return saveFatigueData(time, data);
                    }
                });
    }

    @Override
    public Observable<HomeData> homeData() {
        return Observable.create(new ObservableOnSubscribe<HomeData>() {
            @Override
            public void subscribe(ObservableEmitter<HomeData> emitter) throws Exception {
                Realm realm = Realm.getDefaultInstance();
                try {
                    long startTime = DateFormUtils.oneDayStart(System.currentTimeMillis());
                    //heart
                    HeartData heartData = realm.where(HeartData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (heartData == null) {
                        heartData = new HeartData();
                    } else {
                        heartData = realm.copyFromRealm(heartData);
                    }

                    //oxygen
                    OxygenData oxygenData = realm.where(OxygenData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (oxygenData == null) {
                        oxygenData = new OxygenData();
                    } else {
                        oxygenData = realm.copyFromRealm(oxygenData);
                    }

                    //blood
                    BloodData bloodData = realm.where(BloodData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (bloodData == null) {
                        bloodData = new BloodData();
                    } else {
                        bloodData = realm.copyFromRealm(bloodData);
                    }

                    //step
                    StepData stepData = realm.where(StepData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (stepData == null) {
                        stepData = new StepData();
                    } else {
                        stepData = realm.copyFromRealm(stepData);
                    }

                    //sleep
                    SleepData sleepData = realm.where(SleepData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (sleepData == null) {
                        sleepData = new SleepData();
                    } else {
                        sleepData = realm.copyFromRealm(sleepData);
                    }
                    sleepData.setTotal(sleepData.getDeepValue() + sleepData.getShallowValue());


                    //fatigue
                    FatigueData fatigueData = realm.where(FatigueData.class)
                            .equalTo("userId", currUserId())
                            .greaterThanOrEqualTo("time", startTime)
                            .findAllSorted("time", Sort.DESCENDING)
                            .first(null);
                    if (fatigueData == null) {
                        fatigueData = new FatigueData();
                    } else {
                        fatigueData = realm.copyFromRealm(fatigueData);
                    }

                    emitter.onNext(new HomeData(stepData, sleepData, heartData, bloodData, oxygenData, fatigueData));
                    emitter.onComplete();
                } finally {
                    realm.close();
                }
            }
        });
    }

    @Override
    public Observable<Object> saveDropDownData(final List<StepData> stepDataList, final List<SleepData> sleepDataList, final List<HeartData> heartDataList, final List<OxygenData> oxygenDataList, final List<BloodData> bloodDataList, final List<FatigueData> fatigueDataList) {
        return Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                Realm realm = Realm.getDefaultInstance();
                try {
                    realm.beginTransaction();
                    //step
                    for (StepData item : stepDataList) {
                        StepData stepData = realm.where(StepData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findFirst();
                        if (stepData == null) {
                            realm.copyToRealmOrUpdate(item);
                        } else if (stepData.getValue() != item.getValue()) {
                            realm.copyToRealmOrUpdate(item);
                        } else {
                            item.setUpload(stepData.isUpload());
                            realm.copyToRealmOrUpdate(item);
                        }
//                        if (stepData == null
//                                || stepData.getValue() != item.getValue()
//                                || stepData.getDetailTime() != item.getDetailTime()) {
//                            realm.copyToRealmOrUpdate(item);
//                        }
                    }

                    //sleep
                    for (SleepData item : sleepDataList) {
                        SleepData sleepData = realm.where(SleepData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findFirst();
                        if (sleepData == null) {
                            realm.copyToRealmOrUpdate(item);
                        } else if (sleepData.getDeepValue() != item.getDeepValue()
                                || sleepData.getShallowValue() != item.getShallowValue()) {
                            realm.copyToRealmOrUpdate(item);
                        } else {
                            item.setUpload(sleepData.isUpload());
                            realm.copyToRealmOrUpdate(item);
                        }
//                        if (sleepData == null
//                                || sleepData.getDeepValue() != item.getDeepValue()
//                                || sleepData.getShallowValue() != item.getShallowValue()) {
//                            realm.copyToRealmOrUpdate(item);
//                        }
                    }

                    //heart
                    for (HeartData item : heartDataList) {
                        int size = realm.where(HeartData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findAll().size();
                        if (size == 0) {
                            realm.copyToRealmOrUpdate(item);
                            System.out.println("new HeartData");
                        }
                    }

                    //oxygen
                    for (OxygenData item : oxygenDataList) {
                        int size = realm.where(OxygenData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findAll().size();
                        if (size == 0) {
                            realm.copyToRealmOrUpdate(item);
                            System.out.println("new OxygenData");
                        }
                    }

                    //blood
                    for (BloodData item : bloodDataList) {
                        int size = realm.where(BloodData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findAll().size();
                        if (size == 0) {
                            realm.copyToRealmOrUpdate(item);
                            System.out.println("new BloodData");
                        }
                    }

                    //fatigue
                    for (FatigueData item : fatigueDataList) {
                        int size = realm.where(FatigueData.class)
                                .equalTo("userId", currUserId())
                                .equalTo("time", item.getTime())
                                .findAll().size();
                        if (size == 0) {
                            realm.copyToRealmOrUpdate(item);
                            System.out.println("new FatigueData");
                        }
                    }
                    realm.commitTransaction();
                    emitter.onNext("");
                    emitter.onComplete();
                } finally {
                    realm.close();
                }
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<Object> uploadStep() {
        return Observable
                .create(new ObservableOnSubscribe<List<StepData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<StepData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<StepData> list = realm.where(StepData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<StepData>, ObservableSource<StepData>>() {
                    @Override
                    public ObservableSource<StepData> apply(List<StepData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<StepData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(StepData stepData) throws Exception {
                        return uploadStep(stepData);
                    }
                });
    }


    @Override
    public Observable<NetResult> uploadStep(final StepData stepData) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .step("ServerHandler.SaveStepInfo", currUserId(), "Android", stepData.getValue(), sdf.format(stepData.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            stepData.setUpload(true);
                            realm.copyToRealmOrUpdate(stepData);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadSleep() {
        return Observable
                .create(new ObservableOnSubscribe<List<SleepData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<SleepData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<SleepData> list = realm.where(SleepData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<SleepData>, ObservableSource<SleepData>>() {
                    @Override
                    public ObservableSource<SleepData> apply(List<SleepData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<SleepData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(SleepData stepData) throws Exception {
                        return uploadSleep(stepData);
                    }
                });
    }

    @Override
    public Observable<NetResult> uploadSleep(final SleepData data) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .sleep("ServerHandler.SaveSleepInfo", currUserId(), "Android"
                        , data.getDeepValue() + data.getShallowValue()
                        , data.getDeepValue(), data.getShallowValue(), data.getWalkingTimes()
                        , sdf.format(data.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            data.setUpload(true);
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadHeart() {
        return Observable
                .create(new ObservableOnSubscribe<List<HeartData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<HeartData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<HeartData> list = realm.where(HeartData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<HeartData>, ObservableSource<HeartData>>() {
                    @Override
                    public ObservableSource<HeartData> apply(List<HeartData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<HeartData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(HeartData stepData) throws Exception {
                        return uploadHeart(stepData);
                    }
                });
    }

    @Override
    public Observable<NetResult> uploadHeart(final HeartData data) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .heart("ServerHandler.SaveHeartRateInfo", currUserId(), "Android", data.getValue(), sdf.format(data.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            data.setUpload(true);
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadBlood() {
        return Observable
                .create(new ObservableOnSubscribe<List<BloodData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<BloodData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<BloodData> list = realm.where(BloodData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<BloodData>, ObservableSource<BloodData>>() {
                    @Override
                    public ObservableSource<BloodData> apply(List<BloodData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<BloodData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(BloodData stepData) throws Exception {
                        return uploadBlood(stepData);
                    }
                });
    }

    @Override
    public Observable<NetResult> uploadBlood(final BloodData data) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .blood("ServerHandler.SaveBloodPressureInfo", currUserId(), "Android", data.getHighValue(), data.getLowValue(), sdf.format(data.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            data.setUpload(true);
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadOxygen() {
        return Observable
                .create(new ObservableOnSubscribe<List<OxygenData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<OxygenData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<OxygenData> list = realm.where(OxygenData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<OxygenData>, ObservableSource<OxygenData>>() {
                    @Override
                    public ObservableSource<OxygenData> apply(List<OxygenData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<OxygenData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(OxygenData stepData) throws Exception {
                        return uploadOxygen(stepData);
                    }
                });
    }

    @Override
    public Observable<NetResult> uploadOxygen(final OxygenData data) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .oxygen("ServerHandler.SaveBloodOXInfo", currUserId(), "Android", data.getValue(), sdf.format(data.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            data.setUpload(true);
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadFatigue() {
        return Observable
                .create(new ObservableOnSubscribe<List<FatigueData>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<FatigueData>> emitter) throws Exception {
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            List<FatigueData> list = realm.where(FatigueData.class)
                                    .equalTo("userId", currUserId())
                                    .equalTo("upload", false)
                                    .findAll();
                            list = realm.copyFromRealm(list);
                            emitter.onNext(list);
                            emitter.onComplete();
                        } finally {
                            realm.close();
                        }
                    }
                })
                .flatMap(new Function<List<FatigueData>, ObservableSource<FatigueData>>() {
                    @Override
                    public ObservableSource<FatigueData> apply(List<FatigueData> stepData) throws Exception {
                        return Observable.fromIterable(stepData);
                    }
                })
                .flatMap(new Function<FatigueData, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(FatigueData stepData) throws Exception {
                        return uploadFatigue(stepData);
                    }
                });
    }

    @Override
    public Observable<NetResult> uploadFatigue(final FatigueData data) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return ApiBuilder.createRemoteApi()
                .fatigue("ServerHandler.SaveFatigueInfo", currUserId(), "Android", data.getValue(), sdf.format(data.getTime()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<NetResult>() {
                    @Override
                    public void accept(NetResult o) throws Exception {
                        if (!o.isSuccess()) {
                            return;
                        }
                        Realm realm = Realm.getDefaultInstance();
                        try {
                            realm.beginTransaction();
                            data.setUpload(true);
                            realm.copyToRealmOrUpdate(data);
                            realm.commitTransaction();
                        } finally {
                            realm.close();
                        }
                    }
                });
    }

    @Override
    public Observable<Object> uploadData() {
        return Observable.concatArray(
                uploadStep()
                , uploadSleep()
                , uploadHeart()
                , uploadBlood()
                , uploadOxygen()
                , uploadFatigue()
        );
//        return uploadStep()
////                .flatMap(new Function<Object, ObservableSource<?>>() {
////                    @Override
////                    public ObservableSource<?> apply(Object o) throws Exception {
////                        return uploadSleep();
////                    }
////                })
//                .flatMap(new Function<Object, ObservableSource<?>>() {
//                    @Override
//                    public ObservableSource<?> apply(Object o) throws Exception {
//                        return uploadHeart();
//                    }
//                })
//                .flatMap(new Function<Object, ObservableSource<?>>() {
//                    @Override
//                    public ObservableSource<?> apply(Object o) throws Exception {
//                        return uploadBlood();
//                    }
//                })
//                .flatMap(new Function<Object, ObservableSource<?>>() {
//                    @Override
//                    public ObservableSource<?> apply(Object o) throws Exception {
//                        return uploadOxygen();
//                    }
//                })
//                .flatMap(new Function<Object, ObservableSource<?>>() {
//                    @Override
//                    public ObservableSource<?> apply(Object o) throws Exception {
//                        return uploadFatigue();
//                    }
//                });
    }

    @Override
    public Observable<FatigueData> saveFatigueData(final long time, final OneKeyMeasureData data) {
        return Observable.create(new ObservableOnSubscribe<FatigueData>() {
            @Override
            public void subscribe(ObservableEmitter<FatigueData> emitter) throws Exception {
                Realm realm = Realm.getDefaultInstance();
                try {
                    FatigueData fatigueData = new FatigueData();
                    fatigueData.setTime(time);
                    fatigueData.setUserId(currUserId());
                    fatigueData.setHeart(data.getHeart());
                    fatigueData.setOxygen(data.getOxygen());
                    fatigueData.setBloodHigh(data.getBloodHigh());
                    fatigueData.setBloodLow(data.getBloodLow());

                    long time = DateFormUtils.oneDayStart(System.currentTimeMillis());
                    StepData stepData = realm.where(StepData.class)
                            .equalTo("userId", currUserId())
                            .equalTo("time", time)
                            .findAll()
                            .first(null);
                    if (stepData != null) {
                        fatigueData.setStep(stepData.getValue());
                        fatigueData.setKcal(stepData.getKcal());
                    }
                    SleepData sleepData = realm.where(SleepData.class)
                            .equalTo("userId", currUserId())
                            .equalTo("time", time)
                            .findAll()
                            .first(null);
                    if (sleepData != null) {
                        fatigueData.setDeepValue(sleepData.getDeepValue());
                        fatigueData.setShallowValue(sleepData.getShallowValue());
                    }
                    DeviceSetting deviceSetting = RealmHelper.loadSettings();
                    float point = CalUtils.calFatigue(fatigueData, deviceSetting.getEgeneValue());
                    fatigueData.setValue(point);

                    realm.beginTransaction();
                    realm.copyToRealmOrUpdate(fatigueData);
                    realm.commitTransaction();

                    emitter.onNext(fatigueData);
                    emitter.onComplete();
                } finally {
                    realm.close();
                }
            }
        });
    }

    @Override
    public Observable<Object> delAllData() {
        return Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                Realm realm = Realm.getDefaultInstance();
                try {
                    realm.beginTransaction();
                    realm.where(StepData.class).findAll().deleteAllFromRealm();
                    realm.where(SleepData.class).findAll().deleteAllFromRealm();

                    realm.where(OxygenData.class).findAll().deleteAllFromRealm();
                    realm.where(HeartData.class).findAll().deleteAllFromRealm();
                    realm.where(FatigueData.class).findAll().deleteAllFromRealm();
                    realm.where(BloodData.class).findAll().deleteAllFromRealm();

                    realm.commitTransaction();
                    emitter.onNext("");
                    emitter.onComplete();
                } finally {
                    realm.close();
                }
            }
        });
    }
}
